package org.jiuling.netty.handler;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.timeout.IdleStateEvent;
import org.jiuling.netty.handler.service.BusinessHandlerService;

/**
 * Webocket业务处理器
 * @author 紫灵
 * @date 2025年07月11日 12时00分04秒
 */
public class WebSocketBusinessHandler extends SimpleChannelInboundHandler<WebSocketFrame> {

    /** 业务处理服务 */
    private final BusinessHandlerService<Object> businessHandlerService;

    public WebSocketBusinessHandler(BusinessHandlerService<Object> businessHandlerService) {
        this.businessHandlerService = businessHandlerService;
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        businessHandlerService.preparationProcessing(ctx.channel());
        super.handlerAdded(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, WebSocketFrame frame) throws Exception {
        if (frame instanceof TextWebSocketFrame textWebSocketFrame){
            businessHandlerService.readMessage(channelHandlerContext.channel(),textWebSocketFrame.text());
        }else {
            channelHandlerContext.fireChannelRead(frame.retain());
        }
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete handshakeComplete) {
            businessHandlerService.handshakeComplete(ctx.channel(),handshakeComplete);
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        businessHandlerService.removed(ctx.channel());
        super.handlerRemoved(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        businessHandlerService.exception(ctx.channel(),cause);
        super.exceptionCaught(ctx, cause);
    }
}
